/** 
 * UIMA Annotation Mapper
 * Copyright (C) 2010  Nicolas Hernandez
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package fr.univnantes.lina.uima.mapper.annotation.located;

import java.util.ArrayList;
import java.util.List;

import org.apache.uima.jcas.tcas.Annotation;

/**
 * @author hernandez
 *
 */
public class LocatedAnnotation implements AnnotationComparable_Interface,
RelativelyLocated_Interface {

	private int begin ;
	private int end;

	private List<Annotation> current;
	private List<Annotation> sup;
	private List<Annotation> sub;
	private List<Annotation> next;
	private List<Annotation> previous;
	private List<Annotation> partialNext;
	private List<Annotation> partialPrevious;

	/**
	 * 
	 */
	public LocatedAnnotation() {
		this.setCurrent(new ArrayList<Annotation>());
		this.setSuper(new ArrayList<Annotation>());
		this.setSub(new ArrayList<Annotation>());
		this.setNext(new ArrayList<Annotation>());
		this.setPrevious(new ArrayList<Annotation>());
		this.setPartialNext(new ArrayList<Annotation>());
		this.setPartialPrevious(new ArrayList<Annotation>());
	}

	/**
	 * 
	 */
	public LocatedAnnotation(Annotation a) {
		this.setBegin(a.getBegin());
		this.setEnd(a.getEnd());
		new LocatedAnnotation();
	}

	/**
	 * @return the begin
	 */
	public int getBegin() {
		return begin;
	}

	/**
	 * @param begin the begin to set
	 */
	public void setBegin(int begin) {
		this.begin = begin;
	}

	/**
	 * @return the end
	 */
	public int getEnd() {
		return end;
	}

	/**
	 * @param end the end to set
	 */
	public void setEnd(int end) {
		this.end = end;
	}

	/**
	 * @param current the current to set
	 */
	@Override
	public void setCurrent(List<Annotation> current) {
		this.current = current;
	}

	/**
	 * @param sup the sup to set
	 */
	@Override
	public void setSuper(List<Annotation> sup) {
		this.sup = sup;
	}
	/**
	 * @param sub the sub to set
	 */
	@Override
	public void setSub(List<Annotation> sub) {
		this.sub = sub;
	}

	/**
	 * @param next the next to set
	 */
	@Override
	public void setNext(List<Annotation> next) {
		this.next = next;
	}

	/**
	 * @param previous the previous to set
	 */
	@Override
	public void setPrevious(List<Annotation> previous) {
		this.previous = previous;
	}

	/**
	 * @param partialNext the partialNext to set
	 */
	@Override
	public void setPartialNext(List<Annotation> partialNext) {
		this.partialNext = partialNext;
	}

	/**
	 * @param partialPrevious the partialPrevious to set
	 */
	@Override
	public void setPartialPrevious(List<Annotation> partialPrevious) {
		this.partialPrevious = partialPrevious;
	}

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addCurrent(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addCurrent(Annotation a) {
		this.current.add(a);
	}

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addPrevious(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addPrevious(Annotation a) {
		this.previous.add(a);
	}

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addNext(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addNext(Annotation a) {
		this.next.add(a);
	}
	

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addSuper(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addSuper(Annotation a) {
		this.sup.add(a);
	}

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addSub(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addSub(Annotation a) {
		this.sub.add(a);
	}

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addPartialPrevious(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addPartialPrevious(Annotation a) {
		this.partialPrevious.add(a);
	}

	/** 
	 * Add to the list the annotation
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#addPartialNext(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public void addPartialNext(Annotation a) {
		this.partialNext.add(a);
	}
	
	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addCurrent(List<Annotation> annotationList) {
		this.current.addAll(annotationList);
		
	}
	
	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addNext(List<Annotation> annotationList) {
		this.next.addAll(annotationList);
	}
	
	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addPrevious(List<Annotation> annotationList) {
		this.previous.addAll(annotationList);
		
	}

	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addSuper(List<Annotation> annotationList) {
		this.sup.addAll(annotationList);
		
	}

	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addSub(List<Annotation> annotationList) {
		this.sub.addAll(annotationList);
		
	}

	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addPartialPrevious(List<Annotation> annotationList) {
		this.partialPrevious.addAll(annotationList);
		
	}

	/** 
	 * Add the list to the list the annotation
	 */
	@Override
	public void addPartialNext(List<Annotation> annotationList) {
		this.partialNext.addAll(annotationList);
		
	}



	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getCurrent()
	 */
	@Override
	public List<Annotation> getCurrent() {
		return this.current;
	}

	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getPrevious()
	 */
	@Override
	public List<Annotation> getPrevious() {
		return this.previous;
	}

	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getNext()
	 */
	@Override
	public List<Annotation> getNext() {
		return this.next;
	}

	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getSuper()
	 */
	@Override
	public List<Annotation> getSuper() {
		return this.sup;
	}

	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getSub()
	 */
	@Override
	public List<Annotation> getSub() {
		return this.sub;
	}

	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getPartialPrevious()
	 */
	@Override
	public List<Annotation> getPartialPrevious() {
		return this.partialPrevious;
	}

	/** Return the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getPartialNext()
	 */
	@Override
	public List<Annotation> getPartialNext() {
		return this.partialNext;
	}

	/** Return the list both partial and strict
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getAllPrevious()
	 */
	@Override
	public List<Annotation> getAllPrevious() {
		List<Annotation> concat = new ArrayList<Annotation>(this.previous);
		concat.addAll(this.partialPrevious);
		return concat;
	}

	/** Return the list both partial and strict
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#getAllNext()
	 */
	@Override
	public List<Annotation> getAllNext() {
		List<Annotation> concat = new ArrayList<Annotation>(this.next);
		concat.addAll(this.partialNext);
		return concat;
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmpty(java.util.ArrayList)
	 */
	@Override
	public boolean isEmpty(List<Annotation> aLA) {
		return aLA.isEmpty();
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyCurrent()
	 */
	@Override
	public boolean isEmptyCurrent() {
		return  isEmpty(this.getCurrent());
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyPrevious()
	 */
	@Override
	public boolean isEmptyPrevious() {
		return  isEmpty(this.getPrevious());

	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyNext()
	 */
	@Override
	public boolean isEmptyNext() {
		return  isEmpty(this.getNext());
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptySuper()
	 */
	@Override
	public boolean isEmptySuper() {
		return  isEmpty(this.getSuper());

	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptySub()
	 */
	@Override
	public boolean isEmptySub() {
		return  isEmpty(this.getSub());

	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyPartialPrevious()
	 */
	@Override
	public boolean isEmptyPartialPrevious() {
		return  isEmpty(this.getPartialPrevious());
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyPartialNext()
	 */
	@Override
	public boolean isEmptyPartialNext() {
		return  isEmpty(this.getPartialNext());
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyAllPrevious()
	 */
	@Override
	public boolean isEmptyAllPrevious() {
		return isEmptyPartialPrevious() && isEmptyPrevious(); 
		//return  isEmpty(this.getAllPrevious());
	}

	/** 
	 * Test if the list is empty 
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#isEmptyAllNext()
	 */
	@Override
	public boolean isEmptyAllNext() {
		return isEmptyPartialNext() && isEmptyNext(); 
	}


	/**
	 * test the offset
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.AnnotationComparable_Interface#matchSameOffsets(org.apache.uima.jcas.tcas.Annotation, org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean equalsSameOffsets(Annotation a1, Annotation a2) {
		return (a1.getBegin() == a2.getBegin()) && (a1.getEnd() == a2.getEnd());
	}

	/**
	 * Test if they are the same object (not if they are the same type and the same attributes, and value... shouln't they ?)
	 * http://java.developpez.com/faq/java/?page=divers#DIVERS_equals
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.AnnotationComparable_Interface#match(org.apache.uima.jcas.tcas.Annotation, org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean equals(Annotation a1, Annotation a2) {
		return a1 == a2;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#contains(java.util.ArrayList, org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean contains(List<Annotation> annotationList, Annotation annotation) {
		
		int listSize = annotationList.size() ;
		int counter = 0; 
		boolean contains = false; 
		while ((counter <= listSize) || (!contains)) {
			if (equals(annotationList.get(counter),annotation)) {
				contains = true;
			}
			counter++;
		}
		return contains;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsCurrent(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsCurrent(Annotation a) {
		return  contains(this.getCurrent(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsPrevious(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsPrevious(Annotation a) {
		return  contains(this.getPrevious(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsNext(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsNext(Annotation a) {
		return  contains(this.getNext(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsSuper(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsSuper(Annotation a) {
		return  contains(this.getSuper(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsSub(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsSub(Annotation a) {
		return  contains(this.getSub(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsPartialPrevious(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsPartialPrevious(Annotation a) {
		return  contains(this.getPartialPrevious(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsPartialNext(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsPartialNext(Annotation a) {
		return  contains(this.getPartialNext(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsAllPrevious(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsAllPrevious(Annotation a) {
		return  contains(this.getAllPrevious(),  a) ;
	}

	/** 
	 * Test if the annotation is contained in the list
	 * @see fr.univnantes.lina.uima.mapper.annotation.located.RelativelyLocated_Interface#containsAllNext(org.apache.uima.jcas.tcas.Annotation)
	 */
	@Override
	public boolean containsAllNext(Annotation a) {
		return  contains(this.getAllNext(),  a) ;
	}


}
